package adapter

import (
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"github.com/aliyun/alibaba-cloud-sdk-go/services/sts"
	"strings"
	"time"
)

type OssAdapter struct {
	OssConf
}

type OssConf struct {
	AccessKey string       `json:"access_key"`
	SecretKey string       `json:"secret_key"`
	RoleArny  string       `json:"role_arny"`
	Storage   []OssStorage `json:"storage"`
}

type OssStorage struct {
	Bucket   string `json:"bucket"`
	Region   string `json:"region"`
	Endpoint string `json:"endpoint"`
}

type policy struct {
	Statement []statement `json:"Statement"`
	Version   string      `json:"Version"`
}

type statement struct {
	Action   []string `json:"Action"`
	Effect   string   `json:"Effect"`
	Resource []string `json:"Resource"`
}

type imgToken struct {
	AccessKeyId     string `json:"AccessKeyId"`
	AccessKeySecret string `json:"AccessKeySecret"`
	Expiration      string `json:"Expiration"`
	SecurityToken   string `json:"SecurityToken"`
	WxPolicy        string `json:"WxPolicy"`
	WxSignature     string `json:"WxSignature"`
	Timestamp       int64  `json:"timestamp"`
}

type wxPolicy struct {
	Expiration string        `json:"expiration"`
	Conditions []interface{} `json:"conditions"`
}

func (m *OssAdapter) getRegion(bucket string) string {
	for _, val := range m.Storage {
		if val.Bucket == bucket {
			return val.Region
		}
	}
	return ""
}

// ImgToken 获取上传凭证
func (m *OssAdapter) ImgToken(bucket, key string) (interface{}, error) {
	// 必须json格式
	statementList := make([]statement, 0)
	statementList = append(statementList, statement{
		Action:   []string{"oss:*"},
		Effect:   "Allow",
		Resource: []string{"acs:oss:*:*:*"},
	})

	policyObj := policy{
		Statement: statementList,
		Version:   "1",
	}

	policy, err := json.Marshal(policyObj)
	if err != nil {
		return nil, err
	}

	client, err := sts.NewClientWithAccessKey(m.getRegion(bucket), m.AccessKey, m.SecretKey)
	if err != nil {
		return nil, err
	}

	request := sts.CreateAssumeRoleRequest()

	request.Scheme = "https"
	request.RoleArn = m.RoleArny
	request.RoleSessionName = "session_name" //自定义
	request.Policy = string(policy)          //Policy是阿里云OSS推出的针对Bucket的授权策略，传json格式

	response, err := client.AssumeRole(request)
	if err != nil {
		return nil, err
	}

	// 微信上传相关
	wxPolicyStruct := wxPolicy{
		Expiration: response.Credentials.Expiration,
		Conditions: nil,
	}
	var v1 []string
	v1 = append(v1, "starts-with", "$key", "")
	wxPolicyStruct.Conditions = append(wxPolicyStruct.Conditions, v1)
	wxPolicyByte, _ := json.Marshal(wxPolicyStruct)
	wxPolicyStr := base64.StdEncoding.EncodeToString(wxPolicyByte)

	//hmac ,use sha1
	hkey := []byte(response.Credentials.AccessKeySecret)
	mac := hmac.New(sha1.New, hkey)
	mac.Write([]byte(wxPolicyStr))
	wxSignature := base64.StdEncoding.EncodeToString(mac.Sum(nil))

	return &imgToken{
		AccessKeyId:     response.Credentials.AccessKeyId,
		AccessKeySecret: response.Credentials.AccessKeySecret,
		Expiration:      response.Credentials.Expiration,
		SecurityToken:   response.Credentials.SecurityToken,
		WxPolicy:        wxPolicyStr,
		WxSignature:     wxSignature,
		Timestamp:       time.Now().Unix(),
	}, nil
}

// ImgUrl 获取图片地址
func (m *OssAdapter) ImgUrl(bucket, key string) string {
	if endpoint, ok := m.FileConf()[bucket]; ok {
		return fmt.Sprintf("%s/%s", endpoint, key)
	}
	return ""
}

// FileConf 公共访问配置-阿里云
func (m *OssAdapter) FileConf() map[string]string {
	bucketCfg := map[string]string{}
	for _, val := range m.Storage {
		bucketCfg[val.Bucket] = strings.TrimRight(val.Endpoint, "/")
	}
	return bucketCfg
}
